/*
 * @Description:
 * @Version: 2.0
 * @Autor: gaowei
 * @Date: 2021-04-22 09:05:11
 * @LastEditors: gaowei
 * @LastEditTime: 2021-04-23 04:19:17
 */
const path = require('path');
const chalk = require('chalk');
const crossSpawn = require('cross-spawn');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const webpack = require('webpack');
const fs = require('fs');
const { fsCopy } = require('./utils');
const { getColor, types } = require('./utils');
const { error, success } = require('./utils/logger');

const config = {
  target: 'node12.18',
  // node:{
  //     console:true,
  //     global:true,
  //     proccess:true,
  //     __filename:false,
  //     __dirname:false,
  // },
  mode: 'development',
  entry: {
    'wglint': './bin/wglint.js',
    'wglint-init': './bin/wglint-init.js',
    'wglint-start': './bin/wglint-start.js',
    'wglint-fix': './bin/wglint-fix.js'
    // ".eslintrc.js": "./.eslintrc.js"
  },
  output: {
    path: path.join(__dirname, './dist'),
    filename: '[name].js'
  },
  // devtool: "eval",
  devtool: 'source-map',
  // devtool: "inline-source-map",

  plugins: [
    new CleanWebpackPlugin({
      cleanOnceBeforeBuildPatterns: ['dist']
    })
  ],
  optimization: {
    splitChunks: {
      // cacheGroups: {
      //   vendors: {
      //     name: "chunk-vendors",
      //     test: /[\\/]node_modules[\\/]/,
      //     priority: -10,
      //     chunks: "initial"
      //   },
      //   common: {
      //     name: "chunk-common",
      //     minChunks: 2,
      //     priority: -20,
      //     chunks: "initial",
      //     reuseExistingChunk: true
      //   }
      // }
    },
    minimize: true,
    minimizer: [
      new TerserPlugin({
        // test: /\.js(\?.*)?$/i,    //匹配参与压缩的文件
        terserOptions: {
          format: {
            comments: false,
          },
        },
        extractComments: true,
      })],
  }
};
const promise = function (func) {
  return new Promise((resolve, reject) => {
    func(resolve, reject);
  });
};
const reviewFile = async () => {
  const str = '#!/usr/bin/env node \n';
  const _paths = [
    '',
    // "init",
    // "lint",
    // "fix"
  ];
  for (let _path of _paths) {
    const path = `./dist/wglint${_path ? `-${_path}` : ''}.js`;
    await promise((resolve, reject) => {
      fs.readFile(path, 'utf8', (err, data) => {
        if (err) return console.log(err);
        fs.writeFile(path, `${str}${data}`, (err) => {
          if (err) return console.log(err);
          resolve(true);
        });
      });
    });
  }
};

let exists = function (src, dst, callback) {
  return new Promise((resolve, reject) => {
    // 测试某个路径下文件是否存在
    fs.exists(dst, function (exists) {
      if (exists) { // 不存在
        callback(src, dst);
        resolve();
      } else { // 存在
        fs.mkdir(dst, function () { // 创建目录
          callback(src, dst);
          resolve();
        });
      }
    });
  });
};
const copy = function (src, dst) {
  let stat = fs.stat;
  return new Promise((resolve, reject) => {
    // 读取目录
    fs.readdir(src, async function (err, paths) {
      if (err) throw err;
      for (let i = 0; i < paths.length; i++) {
        const path = paths[i];
        let _src = src + '/' + path;
        let _dst = dst + '/' + path;
        let readable;
        let writable;
        await new Promise((resolve, reject) => {
          stat(_src, function (err, st) {
            if (err) throw err;
            if (st.isFile()) {
              readable = fs.createReadStream(_src);// 创建读取流
              writable = fs.createWriteStream(_dst);// 创建写入流
              readable.pipe(writable);
              resolve();
            } else if (st.isDirectory()) {
              resolve(exists(_src, _dst, copy));
            }
          });
        });
      }
    });
  });

};
const updatePackage = (package_path) => {
  let result = crossSpawn.sync('npm publish', { cwd: package_path, shell: true });
  if (result.status !== 0) {
    const stdout = `${getColor({ str: result.output.toString(), type: 'info' })}\n\n\n${getColor({ str: 'npm 上传失败，请修正后重试', hex: '#ea4d4d' })}\n\n`;
    error(stdout);
    // logger.error('eslint 失败，请修正后重试');
  } else {
    success('npm 上传成功！ ');
  }
};
const createWgShop = async () => {
  fs.rmdirSync(path.join(__dirname, './package/'), { recursive: true }); // 先执行删除
  const package_path = path.join(__dirname, './package');
  await promise((resolve) => { // 再执行创建
    fs.mkdir(package_path, { recursive: true }, (err) => {
      if (err) throw err;
      resolve(true);
    });
  });
  await exists(path.join(__dirname, './dist'), path.join(package_path, 'bin'), copy);
  await fsCopy(path.join(__dirname, './package.json'), path.join(package_path, 'package.json'), copy);
  await fsCopy(path.join(__dirname, './.eslintrc.js'), path.join(package_path, '.eslintrc.js'), copy);
  await fsCopy(path.join(__dirname, './.eslintrc.ts.js'), path.join(package_path, '.eslintrc.ts.js'), copy);
  await fsCopy(path.join(__dirname, './.eslintignore'), path.join(package_path, '.eslintignore'), copy);
  await fsCopy(path.join(__dirname, './.gitignore'), path.join(package_path, '.gitignore'), copy);
  console.log(chalk.bold('完成数据迁移 ， 准备上传到npm'));
  updatePackage(package_path);
  fs.readFile(path.join(__dirname, './package.json'), { encoding: 'utf-8' }, (err, data) => {
    if (err) return console.log(err);

    const json = JSON.parse(data);
    const version = json.version.split('.');
    version[2] = Number(version[2]) + 1;
    json.version = version.join('.');
    fs.writeFile(path.join(path.join(__dirname, './package.json')), JSON.stringify(json, null, 2), (err, data) => {
      if (err) return console.log(err);
      console.log(`package.version 已更新至${json.version}`);
    });
  });
  console.log(chalk.blue(`  当前环境是——>：${process.env.NODE_ENV}`));
  console.log(chalk.cyan('  构建完成啦，开始愉快的玩耍 ~O(∩_∩)O~ \n'));
};
webpack(config, async (err, stats) => {
  if (err) throw err;
  process.stdout.write(stats.toString({
    colors: true,
    modules: false,
    children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
    chunks: false,
    chunkModules: false
  }) + '\n\n');
  if (stats.hasErrors()) {
    console.log(chalk.red('  卧槽：构建失败并出现错误.\n'));
    process.exit(1);
  }
  const reviewFileResult = await reviewFile(); // 重写一个文件
  const createWgShopResult = await createWgShop();
});